selectionmodel: Add gtk_selection_model_user_select_item()
authorBenjamin Otte <otte@redhat.com>
Sat, 19 Oct 2019 19:29:52 +0000 (21:29 +0200)
committerMatthias Clasen <mclasen@redhat.com>
Sat, 30 May 2020 23:26:46 +0000 (19:26 -0400)
I'm not sure this should be public API because it's incredibly awkward.
But it should definitely be shared between list widget implementations.

docs/reference/gtk/gtk4-sections.txt
gtk/gtklistview.c
gtk/gtkselectionmodel.c
gtk/gtkselectionmodel.h

index be3cdfca7d501bbab2b4779da5f7e6191555fdec..3028576cd416fca92dc2a3e7b7186ce465c273d8 100644 (file)
@@ -352,6 +352,8 @@ gtk_selection_model_select_all
 gtk_selection_model_unselect_all
 gtk_selection_model_query_range
 <SUBSECTION>
+gtk_selection_model_user_select_item
+<SUBSECTION>
 gtk_selection_model_selection_changed
 <SUBSECTION Standard>
 GTK_SELECTION_MODEL
index e2eb6105974665c0f0dff10f1a0bdbd1d42ba489..e9fd7b7eb571acbca8db6f18d9aa34d17efd384f 100644 (file)
@@ -616,61 +616,11 @@ gtk_list_view_select_item (GtkListView *self,
                            gboolean     modify,
                            gboolean     extend)
 {
-  GtkSelectionModel *selection_model;
-  gboolean success = FALSE;
-
-  selection_model = gtk_list_item_manager_get_model (self->item_manager);
-
-  if (extend)
-    {
-      guint start_pos = gtk_list_item_tracker_get_position (self->item_manager, self->selected);
-      if (start_pos != GTK_INVALID_LIST_POSITION)
-        {
-          guint max = MAX (start_pos, pos);
-          guint min = MIN (start_pos, pos);
-          if (modify)
-            {
-              if (gtk_selection_model_is_selected (selection_model, start_pos))
-                {
-                  success = gtk_selection_model_select_range (selection_model,
-                                                              min,
-                                                              max - min + 1,
-                                                              FALSE);
-                }
-              else
-                {
-                  success = gtk_selection_model_unselect_range (selection_model,
-                                                                min,
-                                                                max - min + 1);
-                }
-            }
-          else
-            {
-              success = gtk_selection_model_select_range (selection_model,
-                                                          min,
-                                                          max - min + 1,
-                                                          TRUE);
-            }
-        }
-      /* If there's no range to select or selecting ranges isn't supported
-       * by the model, fall through to normal setting.
-       */
-    }
-  if (success)
-    return;
-
-  if (modify)
-    {
-      if (gtk_selection_model_is_selected (selection_model, pos))
-        success = gtk_selection_model_unselect_item (selection_model, pos);
-      else
-        success = gtk_selection_model_select_item (selection_model, pos, FALSE);
-    }
-  else
-    {
-      success = gtk_selection_model_select_item (selection_model, pos, TRUE);
-    }
-  if (success)
+  if (gtk_selection_model_user_select_item (gtk_list_item_manager_get_model (self->item_manager),
+                                            pos,
+                                            modify,
+                                            extend ? gtk_list_item_tracker_get_position (self->item_manager, self->selected)
+                                                   : GTK_INVALID_LIST_POSITION))
     {
       gtk_list_item_tracker_set_position (self->item_manager,
                                           self->selected,
index 7be454fd74932473023950350bfc259d2de64ab3..c5853e87a70dd2874d0d892832ae410160a15d21 100644 (file)
@@ -382,3 +382,90 @@ gtk_selection_model_selection_changed (GtkSelectionModel *model,
   g_signal_emit (model, signals[SELECTION_CHANGED], 0, position, n_items);
 }
 
+/**
+ * gtk_selection_model_user_select_item:
+ * @self: a #GtkSelectionModel
+ * @pos: position selected by the user. If this position is invalid
+ *     no selection will be done.
+ * @modify: %TRUE if the selection should be modified, %FALSE
+ *     if a new selection should be done. This is usually set
+ *     to %TRUE if the user keeps the <Shift> key pressed.
+ * @extend_pos: the position to extend the selection from or
+ *     an invalid position like #GTK_INVALID_LIST_POSITION to not
+ *     extend the selection. Selections are usually extended
+ *     from the last selected position if the user presses the
+ *     <Ctrl> key. The last selected position is stored by the
+ *     widget
+ *
+ * Does a selection according to how GTK list widgets modify
+ * selections, both when clicking rows with the mouse or when using
+ * the keyboard.
+ *
+ * Returns: %TRUE if the last selected position for further calls
+ *     to this function should be updated to @pos, %FALSE if the
+ *     last selected position should not change.
+ **/
+gboolean
+gtk_selection_model_user_select_item (GtkSelectionModel *self,
+                                      guint              pos,
+                                      gboolean           modify,
+                                      guint              extend_pos)
+{
+  gboolean success = FALSE;
+  guint n_items;
+
+  g_return_val_if_fail (GTK_IS_SELECTION_MODEL (self), FALSE);
+
+  n_items = g_list_model_get_n_items (G_LIST_MODEL (self));
+  if (pos >= n_items)
+    return FALSE;
+
+  if (extend_pos < n_items)
+    {
+      guint max = MAX (extend_pos, pos);
+      guint min = MIN (extend_pos, pos);
+      if (modify)
+        {
+          if (gtk_selection_model_is_selected (self, extend_pos))
+            {
+              success = gtk_selection_model_select_range (self,
+                                                          min,
+                                                          max - min + 1,
+                                                          FALSE);
+            }
+          else
+            {
+              success = gtk_selection_model_unselect_range (self,
+                                                            min,
+                                                            max - min + 1);
+            }
+        }
+      else
+        {
+          success = gtk_selection_model_select_range (self,
+                                                      min,
+                                                      max - min + 1,
+                                                      TRUE);
+        }
+      /* If there's no range to select or selecting ranges isn't supported
+       * by the model, fall through to normal setting.
+       */
+    }
+  if (success)
+    return FALSE;
+
+  if (modify)
+    {
+      if (gtk_selection_model_is_selected (self, pos))
+        success = gtk_selection_model_unselect_item (self, pos);
+      else
+        success = gtk_selection_model_select_item (self, pos, FALSE);
+    }
+  else
+    {
+      success = gtk_selection_model_select_item (self, pos, TRUE);
+    }
+
+  return success;
+}
+
index 9e8de6a66b665d3ce6f932e6d092872453804a95..ef5fd1e598db2cc9b30250d008f7cc5aadc6821b 100644 (file)
@@ -118,6 +118,11 @@ void                    gtk_selection_model_query_range         (GtkSelectionMod
                                                                  guint                  *n_items,
                                                                  gboolean               *selected);
 
+GDK_AVAILABLE_IN_ALL
+gboolean                gtk_selection_model_user_select_item    (GtkSelectionModel      *self,
+                                                                 guint                   pos,
+                                                                 gboolean                modify,
+                                                                 guint                   extend_pos);
 /* for implementations only */
 GDK_AVAILABLE_IN_ALL
 void                    gtk_selection_model_selection_changed   (GtkSelectionModel      *model,